package com.project.myproject.lock;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Honorable(mabingqian)
 * @description
 * @date 2020/7/30 14:30
 * @update （更新、优化，注明点）
 */
public class ReentrantLockProject {

    private Lock lock = new ReentrantLock(true);

    FairLock fairLock = new FairLock();

    public void testMethod() {
        lock.lock();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
        }
        lock.unlock();

    }

    //公平锁，谁在队列先给谁
    static final class FairLock extends Sync {

        @Override
        void lock() {
            tryAcquire(1);
        }

        void unlock(int var) {
            tryRelease(var);
        }

        void unlock() {
            tryRelease(1);
        }

        public boolean tryAcquire(int var) {
            Thread thread = Thread.currentThread();
            int state = getState();
            if (state == 0) {
                //如果队列为空，则持有锁，只管当前线程的事，队列头的线程在其获取的时候处理，各管各的
                if (!hasQueuedPredecessors() && this.compareAndSetState(0, var)) {
                    this.setExclusiveOwnerThread(thread);
                    return true;
                }
            } else if (thread == getExclusiveOwnerThread()) {
                //锁的重入
                int newState = state + var;
                setState(newState);
                return true;
            }
            return false;
        }


    }


    /**
     * 非公平锁，谁抢到是谁的，不去队列
     */
    static final class NoFairLock extends Sync {

        @Override
        void lock() {
            nonFairTryAcquire(1);
        }

        void unlock(int var) {
            tryRelease(var);
        }

        void unlock() {
            tryRelease(1);
        }
    }


    abstract static class Sync extends AbstractQueuedSynchronizer {
        public Sync() {
        }
        abstract void lock();

        /**
         * 非公平锁持有锁的过程，是争夺
         * @param var
         * @return
         */
        final boolean nonFairTryAcquire(int var) {
            Thread currentThread = Thread.currentThread();
            int state = getState();
            //没有线程持有锁
            if (state == 0) {
                //cas 改变 state = 1
                if (this.compareAndSetState(0, var)) {
                    //将当前线程标记
                    this.setExclusiveOwnerThread(currentThread);
                    return true;
                }
            } else if (currentThread == getExclusiveOwnerThread()) {
                //当前线程已经持有锁了
                int newState = state + var;
                if (newState < 0) {
                    throw new Error("lock state error");
                }
                setState(newState);
                return true;
            }
            return false;
        }

        /**
         * 释放锁，释放的时候与公平与否无关
         * @param var1
         * @return
         */
        protected final boolean tryRelease(int var1) {
            int state = getState() - var1;
            if (Thread.currentThread() != this.getExclusiveOwnerThread()) {
                throw new RuntimeException("不是这个线程持有的锁");
            } else {
                boolean flag = false;
                if (state == 0) {
                    setState(0);
                    this.setExclusiveOwnerThread(null);
                    flag = true;
                } else {
                    setState(state);
                }
                return flag;
            }

        }
    }

}


